// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <stddef.h>
#include <stdint.h>

#include "base/json/json_reader.h"
#include "base/optional.h"
#include "base/strings/string_piece_forward.h"
#include "net/dns/host_cache.h"

namespace net {

struct Environment {
  Environment() { logging::SetMinLogLevel(logging::LOG_ERROR); }
};

// This fuzzer checks that parsing a JSON list to a HostCache and then
// re-serializing it recreates the original JSON list.
//
// A side effect of this technique is that our distribution of HostCaches only
// contains HostCaches that can be generated by RestoreFromListValue. It's
// conceivable that this doesn't capture all possible HostCaches.
//
// TODO(dmcardle): Check the other direction of this property. Starting from an
// arbitrary HostCache, serialize it and then parse a different HostCache.
// Verify that the two HostCaches are equal.
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
  static Environment env;

  // Attempt to read a JSON list from the fuzzed string.
  base::StringPiece data_view(reinterpret_cast<const char*>(data), size);
  base::Optional<base::Value> value = base::JSONReader::Read(data_view);
  if (!value || !value->is_list())
    return 0;
  const base::ListValue& list_input = base::Value::AsListValue(*value);

  // Parse the HostCache.
  constexpr size_t kMaxEntries = 1000;
  HostCache host_cache(kMaxEntries);
  if (!host_cache.RestoreFromListValue(list_input))
    return 0;

  // Serialize the HostCache.
  base::ListValue serialized;
  host_cache.GetAsListValue(
      &serialized /* entry_list */, true /* include_staleness */,
      HostCache::SerializationType::kRestorable /* serialization_type */);

  CHECK_EQ(list_input, serialized);
  return 0;
}
}  // namespace net
